﻿/// <reference path="uicontrol.ts" />

module UI {

    export class TextBox extends UIControl {

        public type: string = 'TextBox';

        public text: string = '';

        private oldText: string = '';

        public placeholderText: string = '';

        public isPassword: boolean = false;

        private caretPosition: number = 0;

        public onClick: InputEvent = null;

        public onEnter: InputEvent = null;

        public onExit: InputEvent = null;

        public onKeyDown: InputEvent = null;

        public onTextChanged: TextChangedEvent = null;

        constructor(details: any = undefined) {
            super();
            setupControl(this, details);
            this.handleKeyDown = this.handleKeyDownInternal;
        }

        render(context: CanvasRenderingContext2D) {

            if (this.oldText != this.text) {
                this.caretPosition = this.text.length;
                this.oldText = this.text;
            }

            var c = this.computed;

            // Colours based on state
            var stroke = UI.theme.colors.default.outline;
            var text = UI.theme.colors.default.text;
            if (c.state == ControlState.hover) {
                stroke = UI.theme.colors.hover.outline;
                text = UI.theme.colors.hover.text;
            }
            if (c.state == ControlState.down) {
                stroke = UI.theme.colors.down.outline;
                text = UI.theme.colors.down.text;
            }
            if (this.enabled === false) {
                stroke = UI.theme.colors.disabled.outline;
                text = UI.theme.colors.disabled.text;
            }
            if (UI.activeControl == this) {
                text = UI.theme.colors.charm;
            }

            // Outline
            context.lineWidth = 1;
            context.fillStyle = UI.theme.colors.black;
            context.fillRect(c.left, c.top, c.width, c.height);
            context.strokeStyle = stroke;
            context.strokeRect(c.left, c.top, c.width, c.height);

            // Placeholder text
            context.textBaseline = 'middle';
            context.textAlign = 'left';
            context.font = UI.theme.fonts.normal;
            if (this.text == '') {
                context.fillStyle = UI.theme.colors.disabled.text;
                context.fillText(this.placeholderText, c.left + 4, c.middle);
            } else {

                // Entered text
                context.fillStyle = text;
                var actualText = this.isPassword ? Array(this.text.length + 1).join('*') : this.text;
                context.fillText(actualText, c.left + 4, c.middle);
            }            

            // Caret
            if (UI.activeControl == this) {
                var x = c.left + 4 + context.measureText(this.text.substring(0, this.caretPosition)).width;
                context.strokeStyle = UI.theme.colors.charm;
                context.beginPath();
                context.lineWidth = 2;
                context.moveTo(x, c.top + 2);
                context.lineTo(x, c.bottom - 2);
                context.stroke();
            }
        }

        handleKeyDownInternal(sender: UIControl, e: InputArgs) {
            var changed = false;
            if (e.key == 'Escape') {
                UI.activeControl = null;
            } else if (e.key == 'Backspace') {
                if (this.caretPosition > 0) {
                    this.removeAt(this.caretPosition - 1);
                    this.caretPosition--;
                    this.oldText = this.text;
                    changed = true;
                }
            } else if (e.key == 'Delete') {
                if (this.caretPosition < this.text.length) {
                    this.removeAt(this.caretPosition);
                    this.oldText = this.text;
                    changed = true;
                }
            } else if (e.key == 'Home') {
                this.caretPosition = 0;
            } else if (e.key == 'End') {
                this.caretPosition = this.text.length;
            } else if (e.key == 'ArrowLeft') {
                this.caretPosition = Math.max(0, this.caretPosition - 1);
            } else if (e.key == 'ArrowRight') {
                this.caretPosition = Math.min(this.text.length, this.caretPosition + 1);
            } else if (e.key == 'Shift' || e.key == 'Control' || e.key == 'CapsLock' || e.key == 'Enter' || e.key == 'PageUp' || e.key == 'PageDown' ||
                       e.key == 'Insert' || e.key == 'Delete' || e.key == 'Tab' || e.key == 'Alt' || e.key == 'ArrowUp' || e.key == 'ArrowDown') {
                // Do nothing
            } else {
                this.insertAt(this.caretPosition, e.key);
                this.caretPosition = Math.min(this.text.length, this.caretPosition + 1);
                this.oldText = this.text;
                changed = true;
            }
            if (changed && this.onTextChanged !== undefined && this.onTextChanged !== null) {
                this.onTextChanged(this, new TextChangedArgs());
            }
        }

        private insertAt(index: number, text: string) {
            var left = this.text.substr(0, index);
            var right = this.text.substr(index, this.text.length - index);
            this.text = left + text + right;
        }

        private removeAt(index: number) {
            var left = this.text.substr(0, index);
            var right = this.text.substr(index + 1, this.text.length - index - 1);
            this.text = left + right;
        }

    }

}